home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
3D GFX
/
3D GFX.iso
/
amiutils
/
i_l
/
irit5
/
cagd_lib
/
cagdoslo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-30
|
13KB
|
278 lines
/******************************************************************************
* CagdOslo.c - an implementation of the oslo algorithm (1). *
*******************************************************************************
* Written by Gershon Elber, Aug. 92. *
******************************************************************************/
#include <cagd_loc.h>
#define KNOT_INFINITY 1e20
#define OSLO_EPSILON 1e-20
#define OSLO_APX_EQ(x, y) (ABS((x) - (y)) < OSLO_EPSILON)
#ifdef DEBUG
static void PrintAlphaMat(BspKnotAlphaCoeffType *A);
#endif /* DEBUG */
/*****************************************************************************
* DESCRIPTION: M
* Computes the values of the alpha coefficients, Ai,k(j) of order k: M
* M
* n n m m n V
* _ _ _ _ _ V
* C(t) = \ Pi Bi,k(t) = \ Pi \ Ai,k(j) Nj,k(t) = \ ( \ Pi Ai,k(j) ) Nj,k(t)V
* / / / / / V
* - - - - - V
* i=0 i=0 j=0 j=0 i=0 V
* M
* Let T be the original knot vector and let t be the refined one, i.e. T is M
* a subset of t. M
* The Ai,k(j) are computed from the following recursive definition: M
* M
* 1, T(i) <= t(i) < T(i+1) V
* / V
* Ai,1(j) = V
* \ V
* 0, otherwise. V
* V
* V
* T(j+k-1) - T(i) T(i+k) - T(j+k-1) V
* Ai,k(j) = --------------- Ai,k-1(j) + --------------- Ai+1,k-1(j) V
* T(i+k-1) - T(i) T(i+k) - T(i+1) V
* M
* LengthKVT + k is the length of KVT and similarly LengthKVt + k is the M
* length of KVt. In other words, LengthKVT and LengthKVt are the control M
* points len... M
* M
* The output matrix has LengthKVT rows and LengthKVt columns (#cols > #rows) M
* ColIndex/Length hold LengthKVt pairs of first non zero scalar and length ofM
* non zero values in that column, so not all LengthKVT scalars are blended. M
* *
* PARAMETERS: M
* k: Order of geometry. M
* KVT: Original knot vector. M
* LengthKVT: Length of original knot vector. M
* KVt: Refined knot vector. Must contain all knots of KVT. M
* LengthKVt: Length of refined knot vector. M
* *
* RETURN VALUE: M
* BspKnotAlphaCoeffType *: A matrix to multiply the coefficients of the M
* geometry using KVT, in order to get the M
* coefficients under the space defined using M
* KVt that represent the same geometry. M
* *
* KEYWORDS: M
* BspKnotEvalAlphaCoef, alpha matrix, refinement M
*****************************************************************************/
BspKnotAlphaCoeffType *BspKnotEvalAlphaCoef(int k,
CagdRType *KVT,
int LengthKVT,
CagdRType *KVt,
int LengthKVt)
{
int i, j, o;
CagdRType *m, **Rows;
BspKnotAlphaCoeffType
*A = (BspKnotAlphaCoeffType *)
IritMalloc(sizeof(BspKnotAlphaCoeffType));
A -> Order = k;
A -> Length = LengthKVT;
A -> RefLength = LengthKVt;
A -> Matrix = (CagdRType *) IritMalloc(sizeof(CagdRType) * (LengthKVT + 1)
* LengthKVt);
Rows = A -> Rows = (CagdRType **) IritMalloc(sizeof(CagdRType *) *
(LengthKVT + 1));
A -> ColIndex = (int *) IritMalloc(sizeof(int) * LengthKVt);
A -> ColLength = (int *) IritMalloc(sizeof(int) * LengthKVt);
/* Update the row pointers to point onto the matrix rows. */
for (i = 0, j = 0; i <= LengthKVT; i++, j += LengthKVt)
Rows[i] = &A -> Matrix[j];
/* Initialize the matrix with according to order 1: */
for (m = A -> Matrix, i = (LengthKVT + 1) * LengthKVt; i > 0; i--)
*m++ = 0.0;
for (i = 0; i < LengthKVT; i++) {
CagdRType
*RowI = Rows[i],
KVTI = KVT[i],
KVTI1 = KVT[i + 1];
for (j = 0; j < LengthKVt; j++, RowI++) {
if (KVTI <= KVt[j] && KVt[j] < KVTI1)
*RowI = 1.0;
}
}
/* Iterate upto order k: */
for (o = 2; o <= k; o++) {
for (i = 0; i < LengthKVT; i++) {
CagdRType
*RowI = Rows[i],
*RowI1 = Rows[i + 1],
KVTI = KVT[i],
KVTIO = KVT[i + o],
t1 = KVT[i + o - 1] - KVTI,
t2 = KVTIO - KVT[i + 1];
/* If ti == 0, the whole term should be ignored. */
if (t1 < OSLO_EPSILON)
t1 = KNOT_INFINITY;
if (t2 < OSLO_EPSILON)
t2 = KNOT_INFINITY;
for (j = 0; j < LengthKVt; j++, RowI++, RowI1++) {
int jo = j + o;
*RowI = *RowI * (KVt[jo - 1] - KVTI) / t1 +
*RowI1 * (KVTIO - KVt[jo - 1]) / t2;
}
}
}
/* Update the row non zero indices. */
for (i = LengthKVt - 1; i >= 0; i--) {
for (j = 0; j < LengthKVT && OSLO_APX_EQ(Rows[j][i], 0.0); j++);
A -> ColIndex[i] = j;
for (j = LengthKVT - 1; j >= 0 && OSLO_APX_EQ(Rows[j][i], 0.0); j--);
if ((A -> ColLength[i] = j + 1 - A -> ColIndex[i]) <= 0)
CAGD_FATAL_ERROR(CAGD_ERR_DEGEN_ALPHA);
}
return A;
}
/*****************************************************************************
* DESCRIPTION: M
* Frees the BspKnotAlphaCoeffType data structrure. M
* *
* PARAMETERS: M
* A: Alpha matrix to free. M
* *
* RETURN VALUE: M
* void M
* *
* KEYWORDS: M
* BspKnotFreeAlphaCoef, alpha matrix, refinement M
*****************************************************************************/
void BspKnotFreeAlphaCoef(BspKnotAlphaCoeffType *A)
{
IritFree((VoidPtr) A -> Matrix);
IritFree((VoidPtr) A -> Rows);
IritFree((VoidPtr) A -> ColIndex);
IritFree((VoidPtr) A -> ColLength);
IritFree((VoidPtr) A);
}
/*****************************************************************************
* DESCRIPTION: M
* Same as EvalAlphaCoef but the new knot set NewKV is merged with KVT to M
* form the new knot vector KVt. M
* *
* PARAMETERS: M
* k: Order of geometry. M
* KVT: Original knot vector. M
* LengthKVT: Length of original knot vector. M
* NewKV: A sequence of new knots to introduce into KVT. M
* LengthNewKV: Length of new knot sequence. M
* *
* RETURN VALUE: M
* BspKnotAlphaCoeffType *: A matrix to multiply the coefficients of the M
* geometry using KVT, in order to get the M
* coefficients under the space defined using M
* KVt that represent the same geometry. M
* *
* KEYWORDS: M
* BspKnotEvalAlphaCoefMerge, alpha matrix, refinement M
*****************************************************************************/
BspKnotAlphaCoeffType *BspKnotEvalAlphaCoefMerge(int k,
CagdRType *KVT,
int LengthKVT,
CagdRType *NewKV,
int LengthNewKV)
{
BspKnotAlphaCoeffType *A;
if (NewKV == NULL || LengthNewKV == 0) {
A = BspKnotEvalAlphaCoef(k, KVT, LengthKVT, KVT, LengthKVT);
}
else {
int LengthKVt;
CagdRType
*KVt = BspKnotMergeTwo(KVT, LengthKVT + k,
NewKV, LengthNewKV, 0, &LengthKVt);
A = BspKnotEvalAlphaCoef(k, KVT, LengthKVT, KVt, LengthKVt - k);
IritFree(KVt);
}
return A;
}
/*****************************************************************************
* DESCRIPTION: M
* Prepares a refinement vector for the given knot vector domain with n M
* inserted knots equally spaced. M
* *
* PARAMETERS: M
* n: Number of knots to introduce. M
* Tmin: Minimum domain to introduce knots. M
* Tmax: Maximum domain to introduce knots. M
* *
* RETURN VALUE: M
* CagdRType *: A vector of n knots uniformly spaced between TMin and TMax. M
* *
* KEYWORDS: M
* BspKnotPrepEquallySpaced, refinement M
*****************************************************************************/
CagdRType *BspKnotPrepEquallySpaced(int n, CagdRType Tmin, CagdRType Tmax)
{
int i;
CagdRType dt, t, *RefKV;
if (n <= 0) {
CAGD_FATAL_ERROR(CAGD_ERR_WRONG_INDEX);
return NULL;
}
dt = (Tmax - Tmin) / (n + 1),
t = Tmin + dt,
RefKV = (CagdRType *) IritMalloc(sizeof(CagdRType) * n);
for (i = 0; i < n; i++, t += dt) {
RefKV[i] = t;
}
return RefKV;
}
#ifdef DEBUG_OSLO
/*****************************************************************************
* DESCRIPTION: *
* Prints the content of the alpha matrix. *
* *
* PARAMETERS: *
* A: Alpha matrix to print. *
* *
* RETURN VALUE: *
* void *
*****************************************************************************/
static void PrintAlphaMat(BspKnotAlphaCoeffType *A)
{
int i, j;
fprintf(stderr, "Order = %d, Length = %d\n", A -> Order, A -> Length);
for (i = 0; i < A -> Length; i++) {
for (j = 0; j < A -> RefLength; j++)
fprintf(stderr, " %9.5lg", A -> Rows[i][j]);
fprintf(stderr, "\n");
}
fprintf(stderr, " ");
for (j = 0; j < A -> RefLength; j++)
fprintf(stderr, " %3d %3d |", A -> ColIndex[j], A -> ColLength[j]);
fprintf(stderr, "\n");
}
#endif /* DEBUG_OSLO */